home *** CD-ROM | disk | FTP | other *** search
/ TEKNO 1998 April / TEKNO 4-1998.iso / code / 3dcode.txt < prev   
Text File  |  1998-06-28  |  4KB  |  159 lines

  1. Kodsnuttar och formler från "Skapa dina egna virtuella utflykter"
  2. i Tekno 3/98 (med rättningar).
  3.  
  4. ---
  5.  
  6. type
  7.   TPosition = record
  8.     x, y, z: real;
  9.   end;
  10.  
  11. var 
  12.   star: array [1..N_STARS] of TPosition;
  13.  
  14. type
  15.   TVector = TPosition;
  16.   
  17.   TZylon = record
  18.     position: TPosition;
  19.     velocity: TVector;
  20.   end;
  21.   
  22. var 
  23.   zylon: array [1..MAX_ZYLONS] of TZylon;
  24.  
  25. type
  26.   TAttitude = record
  27.     p,       { Pitch }
  28.     b,       { Bank }
  29.     h: real; { Heading }
  30.   end;
  31.  
  32.   TShip = record
  33.     position: TPosition;
  34.     attitude: TAttitude;
  35.     v: real; { Speed }
  36.   end;
  37.  
  38. var
  39.   ship : TShip;
  40.  
  41. function translate(const position, origin: TPosition): TPosition;
  42. begin
  43.   translate.x := position.x - origin.x;
  44.   translate.y := position.y - origin.y;
  45.   translate.z := position.z - origin.z;
  46. end;
  47.  
  48. procedure 2d_rotate(var x, y: real; const angle: real);
  49. var new_x, new_y: real;
  50. begin
  51.   new_x := x * cos(angle) + y * sin(angle);
  52.   new_y := y * cos(angle) - x * sin(angle);
  53.   
  54.   x := new_x;
  55.   y := new_y;
  56. end;
  57.  
  58. function 3d_rotate(const position: TPosition; 
  59.   const attitude: TAttitude): TPosition;
  60. var newPosition: TPosition;
  61. begin
  62.   { Initialize }
  63.   newPosition := position;
  64.  
  65.   { Heading }
  66.   2d_rotate(newPosition.y, newPosition.x, -attitude.h);
  67.   
  68.   { Pitch }
  69.   2d_rotate(newPosition.z, newPosition.y, attitude.p);
  70.   
  71.   { Bank }
  72.   2d_rotate(newPosition.z, newPosition.x, attitude.b);
  73.   
  74.   { Done! }
  75.   3d_rotate := newPosition;
  76. end;
  77.  
  78. x' = [ cos(b)cos(h) - sin(h)sin(p)sin(b) ] x +
  79.      [-cos(b)sin(h) - sin(p)cos(h)sin(b) ] y +
  80.      [ cos(p)sin(b) ] z
  81.      
  82. y' = [ sin(h)cos(p) ] x +
  83.      [ cos(p)cos(h) ] y +
  84.      [ sin(p) ] z;
  85.      
  86. z' = [-cos(h)sin(b) - sin(h)sin(p)cos(b) ] x +
  87.      [ sin(h)sin(b) - sin(p)cos(h)cos(b) ] y +
  88.      [ cos(p)cos(b) ] z
  89.      
  90. const
  91.   PIXELS_PER_METER = 800 / 0.30;
  92.                      
  93. const
  94.   VIEWER_DISTANCE = 0.50; { Meters }
  95.  
  96. var
  97.   mid_u, mid_v: integer;
  98.  
  99. mid_u := window.width div 2;
  100. mid_v := window.height div 2;
  101.  
  102. with position do
  103. begin
  104.   { Projection from transformed coordinates to screen }
  105.   
  106.   u := mid_u + trunc((PIXELS_PER_METER * VIEWER_DISTANCE) * (x / y));
  107.   v := mid_v - trunc((PIXELS_PER_METER * VIEWER_DISTANCE) * (z / y));
  108. end;
  109.  
  110. const
  111.   COLLISION_DISTANCE = 10; { Meters }
  112.   
  113. function collided(const position: TPosition): boolean;
  114. { Must be called with translated position! }
  115. begin
  116.   with position do
  117.     collided := (x * x + y * y + z * z < 
  118.                  COLLISION_DISTANCE * COLLISION_DISTANCE);
  119. end;
  120.  
  121. const
  122.   ZYLON_SIZE = 10; { Meters }
  123.  
  124. function scale_factor(const y: real): real;
  125. { Must be called with Zylon's transformed y coordinate! }
  126. begin
  127.   scale_factor := (PIXELS_PER_METER * VIEWER_DISTANCE) * (ZYLON_SIZE / y)
  128. end;
  129.  
  130. const
  131.   SPRITE_SIZE = 128; { Pixels }
  132.   
  133. type
  134.   TSprite = array [0..SPRITE_SIZE - 1, 
  135.                    0..SPRITE_SIZE - 1] of byte;
  136.   
  137. procedure rescale(const source: TSprite; 
  138.   var destination: TSprite; const scale_factor: real);
  139. { If scale_factor < 1.0, destination must be blank }
  140. begin
  141.   from_i := 0;
  142.   to_i   := 0;
  143.   
  144.   repeat
  145.     from_j := 0;
  146.     to_j   := 0;
  147.     
  148.     repeat
  149.       destination[to_i, to_j] := source[from_i, from_j];
  150.       
  151.       from_j := trunc(to_j * scale_factor);
  152.       to_j   := to_j + 1;
  153.     until ((from_j >= SPRITE_SIZE) or (to_j >= SPRITE_SIZE));
  154.     
  155.     from_i := trunc(to_i * scale_factor);
  156.     to_i   := to_i + 1;
  157.   until ((from_i >= SPRITE_SIZE) or (to_i >= SPRITE_SIZE));
  158. end;
  159.